<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Extending Components
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora153.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora155.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Extending Components</H2>We call a collection of data and methods on the data a component. In
the functional/modular model, a component consists of the definition
of a type and some functions which manipulate the type. Similarly a
component in the object model consists of a hierarchy of classes,
inheriting from one (single) class and therefore having all of its
behaviors. The problem of the extensibility of
components consists of wanting on the one hand to extend the
behaviors and on the other to extend the data
operated on, and all this without modifying the initial program
sources. For example a component <TT>image</TT> can be either a
rectangle or a circle which one can draw or move.<BR>
<BR>
<DIV ALIGN=center>
<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1>
<TR><TD  ALIGN=left NOWRAP>&nbsp;</TD>
<TD  ALIGN=center NOWRAP>rectangle</TD>
<TD  ALIGN=center NOWRAP>circle</TD>
<TD  ALIGN=center NOWRAP>group</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>draw</TD>
<TD  ALIGN=center NOWRAP>X</TD>
<TD  ALIGN=center NOWRAP>X</TD>
<TD  ALIGN=center NOWRAP>&nbsp;</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>move</TD>
<TD  ALIGN=center NOWRAP>X</TD>
<TD  ALIGN=center NOWRAP>X</TD>
<TD  ALIGN=center NOWRAP>&nbsp;</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>grow</TD>
<TD  ALIGN=center NOWRAP>&nbsp;</TD>
<TD  ALIGN=center NOWRAP>&nbsp;</TD>
<TD  ALIGN=center NOWRAP>&nbsp;</TD>
</TR></TABLE>
</DIV><BR>
We might wish to extend the <TT>image</TT> component with the method
<TT>grow</TT> and create groups of images. The behavior of the two
models differs depending on the direction of the extension: data or
methods. First we define, in each model, the common part of the <TT>image</TT>
component, and then we try to extend it.<BR>
<BR>
<A NAME="toc224"></A>
<H3> In the Functional Model</H3>We define the type <I>image</I> as a variant type which contains
two cases. The methods take a parameter of type <I>image</I> and
carry out the required action.


<PRE><BR># <B>type</B><CODE> </CODE>image<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Rect<CODE> </CODE><B>of</B><CODE> </CODE>float<CODE> </CODE><CODE>|</CODE><CODE> </CODE>Circle<CODE> </CODE><B>of</B><CODE> </CODE>float<CODE> </CODE>;;<BR># <B>let</B><CODE> </CODE>draw<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>function</B><CODE> </CODE>Rect<CODE> </CODE>r<CODE> </CODE>-&gt;<CODE> </CODE><CODE>...</CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Circle<CODE> </CODE>c<CODE> </CODE>-&gt;<CODE> </CODE><CODE>...</CODE><CODE> </CODE>;;<BR># <B>let</B><CODE> </CODE>move<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>...</CODE><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
Afterwards, we could encapsulate these global declarations in a
simple module.<BR>
<BR>

<H4> Extension of Methods</H4>The extension of the methods depends on the representation of the type
<I>image</I> in the module. If this type is abstract, it is no longer 
possible to extend the methods. In the case where the type remains
concrete, it is easy to add a <TT>grow</TT> function which changes the
scale of an image by choosing a rectangle or a circle by pattern
matching.<BR>
<BR>

<H4> Extension of Data Types</H4>The extension of data types cannot be achieved with the type
<I>image</I>. In fact Objective CAML types are not extensible, except in
the case of the type <I>exn</I> which represents exceptions. It is
not possible to extend data while keeping the same type, therefore it
is necessary to define a new type <I>n_image</I> in the following
way:
<PRE>
type n_image = I of image | G of n_image * n_image;;
</PRE>Thus we should redefine the methods for this new type, simulating a
kind of inheritance. This becomes complex when there are many
extensions.<BR>
<BR>
<A NAME="toc225"></A>
<H3> In the Object Model</H3>We define the classes <TT>rectangle</TT> and <TT>circle</TT>,
subclasses of the abstract class <TT>image</TT> which has two abstract
methods, <TT>draw</TT> and <TT>move</TT>.


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE>image<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<CODE>:</CODE><I>'a</I><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>draw<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>move<CODE> </CODE><CODE>:</CODE><CODE> </CODE>float<CODE> </CODE><CODE>*</CODE><CODE> </CODE>float<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR># <B>class</B><CODE> </CODE>rectangle<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>w<CODE> </CODE>h<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>image<CODE> </CODE>()<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>x<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>y<CODE> </CODE><CODE>=</CODE><CODE> </CODE>y<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>w<CODE> </CODE><CODE>=</CODE><CODE> </CODE>w<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>h<CODE> </CODE><CODE>=</CODE><CODE> </CODE>h<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>draw<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Printf.printf<CODE> </CODE><CODE>"R: (%f,%f) [%f,%f]"</CODE><CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>w<CODE> </CODE>h<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>move<CODE> </CODE><TT>(</TT>dx<CODE>,</CODE>dy<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>x<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>x<CODE> </CODE><CODE>+.</CODE><CODE> </CODE>dx;<CODE> </CODE>y<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>y<CODE> </CODE><CODE>+.</CODE><CODE> </CODE>dy<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR># <B>class</B><CODE> </CODE>circle<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>x<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>y<CODE> </CODE><CODE>=</CODE><CODE> </CODE>y<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE>r<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>draw<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Printf.printf<CODE> </CODE><CODE>"C: (%f,%f) [%f]"</CODE><CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>r<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>move<CODE> </CODE><TT>(</TT>dx<CODE>,</CODE><CODE> </CODE>dy<TT>)</TT><CODE> </CODE><CODE> </CODE><CODE>=</CODE><CODE> </CODE>x<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>x<CODE> </CODE><CODE>+.</CODE><CODE> </CODE>dx;<CODE> </CODE>y<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>y<CODE> </CODE><CODE>+.</CODE><CODE> </CODE>dy<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR>

</PRE>
<BR>
<BR>
The following program constructs a list of images and displays it.


<PRE><BR># <B>let</B><CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>rectangle<CODE> </CODE><CODE>1</CODE><CODE>.</CODE><CODE> </CODE><CODE>1</CODE><CODE>.</CODE><CODE> </CODE><CODE>3</CODE><CODE>.</CODE><CODE> </CODE><CODE>4</CODE><CODE>.</CODE>;;<BR><CODE>val r : rectangle = &lt;obj&gt;</CODE><BR># <B>let</B><CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>circle<CODE> </CODE><CODE>1</CODE><CODE>.</CODE><CODE> </CODE><CODE>1</CODE><CODE>.</CODE><CODE> </CODE><CODE>4</CODE><CODE>.</CODE>;;<BR><CODE>val c : circle = &lt;obj&gt;</CODE><BR># <B>let</B><CODE> </CODE>l<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE> </CODE><CODE>[</CODE><CODE> </CODE><TT>(</TT>r<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE>image<TT>)</TT>;<CODE> </CODE><TT>(</TT>c<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE>image<TT>)</TT><CODE>]</CODE>;;<BR><CODE>val l : image list = [&lt;obj&gt;; &lt;obj&gt;]</CODE><BR># List.iter<CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>x<CODE> </CODE>-&gt;<CODE> </CODE>x#draw();<CODE> </CODE>print_newline()<TT>)</TT><CODE> </CODE>l;;<BR><CODE>R: (1.000000,1.000000) [3.000000,4.000000]</CODE><BR><CODE>C: (1.000000,1.000000) [4.000000]</CODE><BR><CODE>- : unit = ()</CODE><BR>

</PRE>
<BR>
<BR>

<H4> Extension of Data Types</H4>The data are easily extended by adding a subclass of the class image
in the following way.


<PRE><BR># <B>class</B><CODE> </CODE>group<CODE> </CODE>i1<CODE> </CODE>i2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>i1<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>i1<CODE>:#</CODE>image<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>i2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>i2<CODE>:#</CODE>image<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>draw<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>i1#draw();<CODE> </CODE>print_newline<CODE> </CODE>();<CODE> </CODE>i2#draw()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>move<CODE> </CODE>p<CODE> </CODE><CODE> </CODE><CODE>=</CODE><CODE> </CODE>i1#move<CODE> </CODE>p;<CODE> </CODE>i2#move<CODE> </CODE>p<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR>

</PRE>
<BR>
<BR>
We notice now that the ``type'' <I>image</I> becomes recursive
because the class <I>group</I> depends outside inheritance on
the class <I>image</I>.


<PRE><BR># <B>let</B><CODE> </CODE>g<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>group<CODE> </CODE><TT>(</TT>r<CODE>:&gt;</CODE>image<TT>)</TT><CODE> </CODE><TT>(</TT>c<CODE>:&gt;</CODE>image<TT>)</TT>;;<BR><CODE>val g : group = &lt;obj&gt;</CODE><BR># g#draw();;<BR><CODE>R: (1.000000,1.000000) [3.000000,4.000000]</CODE><BR><CODE>C: (1.000000,1.000000) [4.000000]- : unit = ()</CODE><BR>

</PRE>
<BR>
<BR>

<H4> Extension of Methods</H4>
We define an abstract subclass of <I>image</I> which contains a new method.


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE>e_image<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>image<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>surface<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>float<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR>

</PRE>
<BR>
<BR>
We can define classes <I>e_rectangle</I> and <I>e_circle</I>
which inherit from <I>e_image</I> and from <I>rectangle</I> and
<I>circle</I> respectively. We can then work on extended image to
use this new method. There is a remaining difficulty with the class
<I>group</I>. This contains two fields of type <I>image</I>, so
even when inheriting from the class <I>e_image</I> it will not be
possible to send the <I>grow</I> message to the image fields. It is
thus possible to extend the methods, except in the case of subclasses
corresponding to recursive types.<BR>
<BR>
<A NAME="toc226"></A>
<H3> Extension of Data and Methods</H3>To implement extension in both ways, it is necessary to
define recursive types in the for of a parameterized class. We
redefine the class <I>group</I>.


<PRE><BR># <B>class</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>group<CODE> </CODE>i1<CODE> </CODE>i2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>i1<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>i1<CODE>:</CODE><I>'a</I><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>i2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>i2<CODE>:</CODE><I>'a</I><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>draw<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>i1#draw();<CODE> </CODE>i2#draw()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>move<CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE>i1#move<CODE> </CODE>p;<CODE> </CODE>i2#move<CODE> </CODE>p<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR>

</PRE>
<BR>
<BR>
We then carry on the same principle for the class <I>e_image</I>.


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE><CODE> </CODE>ext_image<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>image<CODE> </CODE>()<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>surface<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>float<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR># <B>class</B><CODE> </CODE>ext_rectangle<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE><CODE> </CODE>w<CODE> </CODE>h<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>ext_image<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>rectangle<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>w<CODE> </CODE>h<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>surface<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>w<CODE> </CODE><CODE>*.</CODE><CODE> </CODE>h<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR># <B>class</B><CODE> </CODE>ext_circle<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE><CODE> </CODE>r<CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>ext_image<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>circle<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>r<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>surface<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>3</CODE><CODE>.</CODE><CODE>1</CODE><CODE>4</CODE><CODE> </CODE><CODE>*.</CODE><CODE> </CODE>r<CODE> </CODE><CODE>*.</CODE>r<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR>

</PRE>
<BR>
<BR>
The extension of the class <I>group</I> thus becomes


<PRE><BR># <B>class</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>ext_group<CODE> </CODE>ei1<CODE> </CODE>ei2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>image()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>group<CODE> </CODE>ei1<CODE> </CODE>ei2<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>surface<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ei1#surface()<CODE> </CODE><CODE>+.</CODE><CODE> </CODE>ei2#surface<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR>

</PRE>
<BR>
<BR>
We get the following program which constructs a list <TT>le</TT> of
the type <I>ext_image</I>.


<PRE><BR># <B>let</B><CODE> </CODE>er<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>ext_rectangle<CODE> </CODE><CODE>1</CODE><CODE>.</CODE><CODE> </CODE><CODE>1</CODE><CODE>.</CODE><CODE> </CODE><CODE>2</CODE><CODE>.</CODE><CODE> </CODE><CODE>4</CODE><CODE>.</CODE><CODE> </CODE>;;<BR><CODE>val er : ext_rectangle = &lt;obj&gt;</CODE><BR># <B>let</B><CODE> </CODE>ec<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>ext_circle<CODE> </CODE><CODE>1</CODE><CODE>.</CODE><CODE> </CODE><CODE>1</CODE><CODE>.</CODE><CODE> </CODE><CODE>8</CODE><CODE>.</CODE>;;<BR><CODE>val ec : ext_circle = &lt;obj&gt;</CODE><BR># <B>let</B><CODE> </CODE>eg<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>ext_group<CODE> </CODE>er<CODE> </CODE>ec;;<BR><CODE>val eg : ext_rectangle ext_group = &lt;obj&gt;</CODE><BR># <B>let</B><CODE> </CODE>le<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>[</CODE><CODE> </CODE><TT>(</TT>er<CODE>:&gt;</CODE>ext_image<TT>)</TT>;<CODE> </CODE><TT>(</TT>ec<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE>ext_image<TT>)</TT>;<CODE> </CODE><TT>(</TT>eg<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE>ext_image<TT>)</TT><CODE>]</CODE>;;<BR><CODE>val le : ext_image list = [&lt;obj&gt;; &lt;obj&gt;; &lt;obj&gt;]</CODE><BR># List.map<CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>x<CODE> </CODE>-&gt;<CODE> </CODE>x#surface()<TT>)</TT><CODE> </CODE>le;;<BR><CODE>- : float list = [8; 200.96; 208.96]</CODE><BR>

</PRE>
<BR>
<BR>

<H4> Generalization</H4>To generalize the extension of the methods it is preferable to
integrate some functions in a method <TT>handler</TT> and to
construct a parameterized class with the return type of the method.
For this we define the following class:


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE><CODE> </CODE>get_image<CODE> </CODE><TT>(</TT>f<CODE>:</CODE><CODE> </CODE><I>'b</I><CODE> </CODE>-&gt;<CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<CODE>:</CODE><I>'b</I><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>image<CODE> </CODE>()<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>handler<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>f<TT>(</TT>self<TT>)</TT><CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR>

</PRE>
<BR>
<BR>
The following classes then possess an additional functional parameter for
the construction of their instances.


<PRE><BR># <B>class</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>get_rectangle<CODE> </CODE>f<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE><CODE> </CODE>w<CODE> </CODE>h<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<CODE>:</CODE><I>'b</I><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>get_image<CODE> </CODE>f<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>rectangle<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>w<CODE> </CODE>h<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>get<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<CODE>,</CODE>w<CODE>,</CODE>h<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR># <B>class</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>get_circle<CODE> </CODE>f<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE><CODE> </CODE>r<CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<CODE>:</CODE><I>'b</I><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>get_image<CODE> </CODE>f<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>circle<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>r<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>get<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<CODE>,</CODE>r<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR>

</PRE>
<BR>
<BR>
The extension of the class <I>group</I> thus takes two type parameters:


<PRE><BR># <B>class</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>,</CODE><I>'c</I><CODE>]</CODE><CODE> </CODE>get_group<CODE> </CODE>f<CODE> </CODE>eti1<CODE> </CODE>eti2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>get_image<CODE> </CODE>f<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE><I>'c</I><CODE>]</CODE><CODE> </CODE>group<CODE> </CODE>eti1<CODE> </CODE>eti2<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>get<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>i1<CODE>,</CODE>i2<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR>

</PRE>
<BR>
<BR>
We get the program which extends the method of the instance of
<I>get_image</I>.


<PRE><BR># <B>let</B><CODE> </CODE>etr<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>get_rectangle<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>r<CODE> </CODE>()<CODE> </CODE>-&gt;<CODE> </CODE><B>let</B><CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<CODE>,</CODE>w<CODE>,</CODE>h<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>r#get<CODE> </CODE><B>in</B><CODE> </CODE>w<CODE> </CODE><CODE>*.</CODE><CODE> </CODE>h<TT>)</TT><CODE> </CODE><CODE>1</CODE><CODE>.</CODE><CODE> </CODE><CODE>1</CODE><CODE>.</CODE><CODE> </CODE><CODE>2</CODE><CODE>.</CODE><CODE> </CODE><CODE>4</CODE><CODE>.</CODE><CODE> </CODE>;;<BR><CODE>val etr : float get_rectangle = &lt;obj&gt;</CODE><BR># <B>let</B><CODE> </CODE>etc<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>get_circle<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>c<CODE> </CODE>()<CODE> </CODE>-&gt;<CODE> </CODE><B>let</B><CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<CODE>,</CODE>r<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>c#get<CODE> </CODE><B>in</B><CODE> </CODE><CODE>3</CODE><CODE>.</CODE><CODE>1</CODE><CODE>4</CODE><CODE> </CODE><CODE>*.</CODE><CODE> </CODE>r<CODE> </CODE><CODE>*.</CODE><CODE> </CODE>r<TT>)</TT><CODE> </CODE><CODE>1</CODE><CODE>.</CODE><CODE> </CODE><CODE>1</CODE><CODE>.</CODE><CODE> </CODE><CODE>8</CODE><CODE>.</CODE>;;<BR><CODE>val etc : float get_circle = &lt;obj&gt;</CODE><BR># <B>let</B><CODE> </CODE>etg<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>get_group<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>g<CODE> </CODE>()<CODE> </CODE>-&gt;<CODE> </CODE><B>let</B><CODE> </CODE><TT>(</TT>i1<CODE>,</CODE>i2<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>g#get<CODE> </CODE><B>in</B><CODE> </CODE>i1#handler()<CODE> </CODE><CODE>+.</CODE><CODE> </CODE>i2#handler()<TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT>etr<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE>float<CODE> </CODE>get_image<TT>)</TT><CODE> </CODE><TT>(</TT>etc<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE>float<CODE> </CODE>get_image<TT>)</TT>;;<BR><CODE>val etg : (float, float get_image) get_group = &lt;obj&gt;</CODE><BR># <B>let</B><CODE> </CODE>gel<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>[</CODE><CODE> </CODE><TT>(</TT>etr<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE>float<CODE> </CODE>get_image<TT>)</TT><CODE> </CODE>;<CODE> </CODE><TT>(</TT>etc<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE>float<CODE> </CODE>get_image<TT>)</TT><CODE> </CODE>;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT>etg<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE>float<CODE> </CODE>get_image<TT>)</TT><CODE> </CODE><CODE>]</CODE>;;<BR><CODE>val gel : float get_image list = [&lt;obj&gt;; &lt;obj&gt;; &lt;obj&gt;]</CODE><BR># List.map<CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>x<CODE> </CODE>-&gt;<CODE> </CODE>x#handler()<TT>)</TT><CODE> </CODE>gel;;<BR><CODE>- : float list = [8; 200.96; 208.96]</CODE><BR>

</PRE>
<BR>
<BR>
The extension of data and methods is easier in the object model when
it is combined with the functional model.<BR>
<BR>
<HR>
<A HREF="book-ora153.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora155.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
